#include "apue.h"
#include <errno.h>
#include <netdb.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/stat.h>
#include <stdint.h>
#include <time.h>

int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen) {
    int fd, err;
    int reuse= 1;

    if ((fd= socket(addr->sa_family, type, 0)) < 0)
        return(-1);
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0)
        goto errout; 
    if (bind(fd, addr, alen) < 0)
        goto errout;
    if (type == SOCK_STREAM || type == SOCK_SEQPACKET)
        if (listen(fd, qlen) < 0)
            goto errout;
    return fd;

errout:
    err= errno;
    close(fd);
    errno= err;
    return(-1);
}

void print_stat(struct stat *st) {
    char *ptr;
    if (S_ISREG(st->st_mode)) 
        ptr= "regular";
    else if (S_ISDIR(st->st_mode))
        ptr= "directory";
    else if (S_ISCHR(st->st_mode))
        ptr="character special";
    else if (S_ISBLK(st->st_mode))
        ptr= "block special";
    else if (S_ISFIFO(st->st_mode))
        ptr= "fifo";
    else if (S_ISLNK(st->st_mode))
        ptr= "symbolic link";
    else if (S_ISSOCK(st->st_mode))
        ptr= "socket";
    else 
        ptr= "** unknown mode **";
    printf("%s\n", ptr);


    printf("ID of containing device: [%jx, %jx]\n", 
            (uintmax_t)major(st->st_dev), 
            (uintmax_t)minor(st->st_dev));

    printf("I-node number: %ju\n", (uintmax_t)st->st_ino);
    printf("Mode: %jo(octal)\n", (uintmax_t)st->st_mode);
    printf("Link count: %ju\n", (uintmax_t)st->st_nlink);
    printf("Ownership:  UID=%ju  GID=%ju\n", (uintmax_t)st->st_uid, (uintmax_t)st->st_gid);
    printf("Preferred I/O block size: %jd bytes\n", (intmax_t)st->st_blksize);
    printf("File size: %jd bytes\n", (intmax_t)st->st_size);
    printf("Blocks allocated: %jd\n", (intmax_t)st->st_blocks);
    printf("Last status change: %s", ctime(&st->st_ctime));
    printf("Last file access: %s", ctime(&st->st_atime));
    printf("Last file modification: %s", ctime(&st->st_mtime));
}

int main() {
    struct addrinfo *ailist, *aip;
    struct addrinfo hint;
    int fd, err, n;
    char *host;
    struct stat st;

    if ((n= sysconf(_SC_HOST_NAME_MAX)) < 0)
        n= 256;   /* best guess */
    if ((host= malloc(n)) == NULL)
        err_sys("malloc error");
    if ((err= gethostname(host, n)) < 0)
        err_sys("gethostname error");

    memset(&hint, 0, sizeof(hint));
    hint.ai_flags= AI_CANONNAME;
    hint.ai_socktype= SOCK_STREAM;
    hint.ai_addr= NULL;
    hint.ai_next= NULL;

    if ((err= getaddrinfo(host, "ruptime", &hint, &ailist)) != 0)
        err_quit("ruptimed: getaddrinfo error: %s", gai_strerror(err));

    printf("host: %s\n", host);
    for (aip= ailist; aip!=NULL; aip= ailist->ai_next) {
        if ((fd= initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, 0)) < 0) {
            err= errno;
            continue;
        }
        if (fstat(fd, &st) < 0)
            err_sys("fstat error");

        print_stat(&st);

        exit(0);
                
    }
    err_exit(err, "initserver error: %s\n");
}
